#!/usr/bin/python

import pygame
import render_engine.RenderEngine
from level_manager import LevelManager
from entity_manager import EntityManager, Entity, MoveableEntity, PlayerEntity, FollowMonster, SpawnerEntity, GrowEntity
from input_manager import InputManager
from resource_manager import ResourceManager
from level_manager import PathFinder
from ui_manager import UIManager



# Don't construct me, instead use getGameEngine()
class GameEngine:

    # Obvious
    def __init__(self, magicConstructor = None):
        if magicConstructor != "blahblah":
            raise Exception("Don't instantiate GameEngine() directly. Instead use getGameEngine().")
        self.m_absoluteTime = 0

    def initialize(self):
        # Init stuff here
        (numpass, numfail) = pygame.init()
        self.m_gameClock = pygame.time.Clock()
        self.m_renderEngine = render_engine.RenderEngine.RenderEngine()
        self.m_resourceManager = ResourceManager.ResourceManager()
        self.m_resourceManager.addResourcePath("images/")

        #Init our LevelManager
        #TODO : Find different place to load level
        self.m_levelManager = LevelManager.LevelManager(self.m_resourceManager)
        
        # Initialize entity manager
        self.m_entityManager = EntityManager.EntityManager()

        #Init UIManager
        self.m_UIManager = UIManager.UIManager(self.m_resourceManager)

        self.m_renderEngine.registerObject(self.m_levelManager,render_engine.RenderEngine.RENDER_OBJ_BACKGROUND)
        
        
        self.m_renderEngine.registerObject(self.m_UIManager, render_engine.RenderEngine.RENDER_OBJ_UI)



        # Create a player entity
        player = PlayerEntity.PlayerEntity()
        # Register for updates and draw
        self.m_entityManager.registerEntity(player, render_engine.RenderEngine.RENDER_OBJ_CHARACTER)
        # Register as player entity with entity manager
        self.m_entityManager.setPlayerEntity(player)
               
        #Load our first level
        self.m_levelManager.loadLevel(1)

        # Init our path finder
        self.m_pathFinder = PathFinder.PathFinder()

        # Set player properties
        player.setSize(2,2)
        player.loadAnimationImage("data.CharacterSprite")
 
        #Lets start our Music
        #TODO : We are going to need a music manager of sorts
        try:
            musicFile = "music/White_Wedding.mid"
            pygame.mixer.init(44100,-16,2,1024)
            pygame.mixer.music.set_volume(0.8)
            pygame.mixer.music.load(musicFile)
            pygame.mixer.music.play()
            print "Music Loaded"
        except pygame.error:
            print "No audio device. Music not started."




        # Create input manager
        self.m_inputManager = InputManager.InputManager(player)
        self.m_player = player

    # Obvious
    def cleanup(self):
        pygame.quit()


    # Main runloop - continues until it ends.
    def run(self):
        print "Game running..."
        try:
            # Tick once here, so that the first tick in the loop uses this as the 'zero' time
            self.m_gameClock.tick(50)
            while (True):
                # Advance the game clock
                self.m_gameClock.tick(50) 
                self.m_absoluteTime += self.m_gameClock.get_time()
                #print "Tick time is "+str(self.m_gameClock.get_time())

                # Process user input
                self.m_inputManager.frameUpdate(self.m_gameClock.get_time(), self.m_absoluteTime)

                # Update simulation
                self.m_entityManager.frameUpdate(self.m_gameClock.get_time(), self.m_absoluteTime)

                # Update resource manager stats
                self.m_resourceManager.frameUpdate(self.m_gameClock.get_time(), self.m_absoluteTime)

                # Render simulation
                self.m_renderEngine.renderFrame(self.m_gameClock.get_time(), self.m_absoluteTime)


        except KeyboardInterrupt as exInstance:
            print "User requested exit."
        

    # Retrieve the main game clock - callers should only use get_time(), get_rawtime() and get_fps() on this
    def getClock(self):
        return self.m_gameClock

    # Retrieve the UI Manager
    def getUIManager(self):
        return self.m_UIManager
    
    # Retrieve the render engine
    def getRenderEngine(self):
        return self.m_renderEngine

    # Get the level manager
    def getLevelManager(self):
        return self.m_levelManager

    # Get the entity manager
    def getEntityManager(self):
        return self.m_entityManager

    # Get the input manager
    def getInputManager(self):
        return self.m_inputManager

    def getPathFinder(self):
        return self.m_pathFinder

    # Retrieve the resource manager
    def getResourceManager(self):
        return self.m_resourceManager
    
    # Retrieve the player entity
    def getPlayerEntity(self):
        return self.m_player
        
# One and only game engine 
g_gameEngine = None


def getGameEngine():
    global g_gameEngine
    if g_gameEngine is None:
        g_gameEngine = GameEngine("blahblah")
        g_gameEngine.initialize()
    return g_gameEngine
           





